#include "SimpleWin.h"
void Quit_CB(Fl_Widget *, void *data)
{
    SimpleWin* win = (SimpleWin*)data;
    win->change_size(win);
    //line_size_ = 19;
    //win->redraw();
}
SimpleWin::SimpleWin(int w, int h, const char* l): Fl_Double_Window(w,h, l)
{
    //ctor
    // box = new Fl_Box (20, 40, 260, 100, "Hello World!");
    menu = new Fl_Menu_Bar(0, 0, w, 25);
    //std::cout << "line_end_xx_: " << line_end_xx_ << " line_end_yy_: " << line_end_yy_ << std::endl;
    menu->add(u8"棋盘/线数", 0, Quit_CB, (void*)this);

}
SimpleWin::SimpleWin(int x, int y, int w, int h, const char* l): Fl_Double_Window(x, y, w, h, l)
{

}
int SimpleWin::handle(int e)
{
    int rect = Fl_Double_Window::handle(e);
    switch (e)
    {
    case FL_RELEASE:
        // 先改变下颜色
        change_color();
        int x = current_x();
        int y = current_y();

        // std::cout << "x: " << x << " y: " << y << std::endl;
        int c_x = calc(x);
        int c_y = calc(y);
        // 大于最大边线
        if(!down_check(c_x, c_y))
        {
            break;
        }
        //std::cout << "c_x: " << c_x << " c_y: " << c_y << std::endl;
        //ChesPieces cp(x, y, next_color_);
        current_color_ = next_color_;
        ChesPieces cp(c_x, c_y, next_color_);

        current_cp_ = cp;
        current_calc_x_ = c_x;
        current_calc_y_ = c_y;

        ches_pieces_.push_back(cp);
        std::string map_key = gerer_key(c_x, c_y);
        // 把棋子映射一下，后面判断用
        xy_mapper_.insert(std::make_pair(map_key, cp));
        damage(FL_DAMAGE_USER1);
        // 检测4条线
        bool one = check_one(c_x, c_y);
        bool two = check_two(c_x, c_y);
        bool three = check_three(c_x, c_y);
        bool four = check_four(c_x, c_y);
        if(one | two | three | four)
        {
            // 已经分出胜负
            win_ = 1;
            //char msg[80];
            std::string str = color_name();
            str.append("胜,重新开局");
            //sprintf(msg, u8"%s胜,重新开局");
            switch (fl_choice(str.c_str(), u8"是", u8"否", 0) )
            {
            case 0:
            {
                reset();
            }
            case 1:
            {
                reset();
            }
            }
        }
        break;
    }
    return rect;
}
bool SimpleWin::down_check(int c_x, int c_y)
{
    if(c_x > line_end_x_)
    {
        fl_alert("无效落子!");
        return false;
    }
    if(c_x < line_start_x_)
    {
        fl_alert("无效落子!");
        return false;
    }
    if(c_y > line_end_y_)
    {
        fl_alert("无效落子!");
        return false;
    }
    if(c_y < line_start_y_)
    {
        fl_alert("无效落子!");
        return false;
    }
    std::string map_key = gerer_key(c_x, c_y);
    std::map<std::string, ChesPieces>::iterator search_map;
    search_map = xy_mapper_.find(map_key);
    if(search_map != xy_mapper_.end())
    {
        fl_alert("当前位置已经有棋子，落子失败!");
        return false;
    }
    if(win_)
    {
        fl_alert("已经分出胜负，请重新开局!");
        return false;
    }
    return true;
}
void SimpleWin::reset()
{
    win_ = 0;
    ches_pieces_.clear();
    xy_mapper_.clear();
    redraw();
}
void SimpleWin::draw_chess()
{
    for(ChesPieces cp: ches_pieces_)
    {
        int x = cp.x();
        int y = cp.y();
        int color = cp.color();
        //fl_color(color);
        //fl_rectf(x, y, cr_, cr_);
        fl_begin_polygon();
        fl_color(color);
        fl_circle(x, y, cr_);
        fl_end_polygon();
    }
}
int SimpleWin::current_x()
{
    return (int)Fl::event_x();
}
int SimpleWin::current_y()
{
    return (int)Fl::event_y();
}
void SimpleWin::draw()
{
    // 动态改变线条，重新计算边界
    // 最大x边线
    line_end_x_ = ((line_size_ - 1) * line_cr_) + line_start_x_;
    // 最大y边线
    line_end_y_ = ((line_size_ - 1) * line_cr_) + line_start_y_;

    if (damage() == FL_DAMAGE_USER1 )
    {
        draw_chess();
        return;
    }
    Fl_Double_Window::draw();
    {

        std::cout << "draw line_size_:  " << line_size_ << std::endl;
        // 画棋盘
        for(int i = 0; i < line_size_; ++ i)
        {
            fl_color(FL_BLACK);
            fl_line(line_start_x_+(i*line_cr_), line_start_y_, line_start_x_+(i*line_cr_), line_end_y_);
        }
        for(int i = 0; i < line_size_; ++ i)
        {
            fl_line(line_start_x_, line_start_y_+i*line_cr_,  line_end_x_, line_start_y_+i*line_cr_);
        }
    }
    draw_chess();
}
int SimpleWin::calc(int x)
{
    int v = x % line_cr_;
    if(v < line_cr_/2)
    {
        // 不足一半的部分舍去
        return x - v;
    }
    else
    {
        // 超过一半，变成整数陪
        return  line_cr_* ((x/line_cr_) + 1);
    }
}
std::string SimpleWin::gerer_key(int x, int y)
{
    return std::to_string(x).append("|").append(std::to_string(y));
}
void SimpleWin::change_color()
{
    int c_size = ches_pieces_.size();
    int v = c_size % 2;
    if(v)
    {
        next_color_ = 88;
    }
    else
    {
        next_color_ = 56;
    }
    //std::cout << "next color: " << next_color_ << " size: " << c_size << " v: " << v << std::endl;
}

SimpleWin::~SimpleWin()
{
    //dtor
}
int SimpleWin::current_color()
{
    return next_color_;
}
std::string SimpleWin::color_name()
{
    if(current_color() == 88)
        return u8"红棋";
    else
        return u8"黑棋";
}
bool SimpleWin::check_one(int x, int y)
{
    std::vector<int> coll_one;
    // std::cout << "current x: " << x << " y: " << y << std::endl;
    // 向前推进4个坐标
    int start = x - (line_cr_ * 4);
    // 最多取9个就可以分胜负
    for(int i = 0; i < 9; ++ i)
    {
        //std::cout << "x: " << start + (i * line_cr_) << " y: " << y << std::endl;
        int new_x = start + (i * line_cr_);
        int new_y = y;
        std::string map_key = gerer_key(new_x, new_y);
        std::map<std::string, ChesPieces>::iterator search_map;
        search_map = xy_mapper_.find(map_key);
        // 找到了，说明目标位标有棋子
        int search_color = 0;
        if(search_map != xy_mapper_.end())
        {
            ChesPieces search_cp = xy_mapper_[map_key];
            search_color = search_cp.color();
        }
        coll_one.insert(std::end(coll_one), search_color);
    }
    //std::copy(std::begin(coll_one), std::end(coll_one), std::ostream_iterator<int>(std::cout, " "));
    //std::cout << std::endl;
    std::vector<int>::iterator serarch_n_iter;
    // 有五个相同的棋子，分出胜负
    serarch_n_iter = std::search_n(std::begin(coll_one), std::end(coll_one), 5, current_color_);
    if(serarch_n_iter != std::end(coll_one))
    {
        return true;
    }
    return false;
}
bool SimpleWin::check_two(int x, int y)
{
    std::vector<int> coll_two;
    //std::cout << "current x: " << x << " y: " << y << std::endl;
    // 向前推进4个坐标
    int start = y - (line_cr_ * 4);
    // 最多取9个就可以分胜负
    for(int i = 0; i < 9; ++ i)
    {
        //std::cout << "x: " << x << " y: " << start + (i * line_cr_) << std::endl;
        int new_x = x;
        int new_y = start + (i * line_cr_);
        std::string map_key = gerer_key(new_x, new_y);
        std::map<std::string, ChesPieces>::iterator search_map;
        search_map = xy_mapper_.find(map_key);
        // 找到了，说明目标位标有棋子
        int search_color = 0;
        if(search_map != xy_mapper_.end())
        {
            ChesPieces search_cp = xy_mapper_[map_key];
            search_color = search_cp.color();
        }
        coll_two.insert(std::end(coll_two), search_color);
    }
    //std::copy(std::begin(coll_two), std::end(coll_two), std::ostream_iterator<int>(std::cout, " "));
    //std::cout << std::endl;
    std::vector<int>::iterator serarch_n_iter;
    // 有五个相同的棋子，分出胜负
    serarch_n_iter = std::search_n(std::begin(coll_two), std::end(coll_two), 5, current_color_);
    if(serarch_n_iter != std::end(coll_two))
    {
        return true;
    }
    return false;
}
bool SimpleWin::check_three(int x, int y)
{
    std::vector<int> coll_two;
    //std::cout << "current x: " << x << " y: " << y << std::endl;
    // 向前推进4个坐标
    int start_x = x - (line_cr_ * 4);
    int start_y = y - (line_cr_ * 4);
    // 最多取9个就可以分胜负
    for(int i = 0; i < 9; ++ i)
    {
        //std::cout << "x: " << x << " y: " << start + (i * line_cr_) << std::endl;
        int new_x = start_x + (i * line_cr_);
        int new_y = start_y + (i * line_cr_);
        std::string map_key = gerer_key(new_x, new_y);
        std::map<std::string, ChesPieces>::iterator search_map;
        search_map = xy_mapper_.find(map_key);
        // 找到了，说明目标位标有棋子
        int search_color = 0;
        if(search_map != xy_mapper_.end())
        {
            ChesPieces search_cp = xy_mapper_[map_key];
            search_color = search_cp.color();
        }
        coll_two.insert(std::end(coll_two), search_color);
    }
    //std::copy(std::begin(coll_two), std::end(coll_two), std::ostream_iterator<int>(std::cout, " "));
    //std::cout << std::endl;
    std::vector<int>::iterator serarch_n_iter;
    // 有五个相同的棋子，分出胜负
    serarch_n_iter = std::search_n(std::begin(coll_two), std::end(coll_two), 5, current_color_);
    if(serarch_n_iter != std::end(coll_two))
    {
        return true;
    }
    return false;
}
bool SimpleWin::check_four(int x, int y)
{
    std::vector<int> coll_two;
    //std::cout << "current x: " << x << " y: " << y << std::endl;
    // 向前推进4个坐标
    int start_x = x - (line_cr_ * 4);
    int start_y = y + (line_cr_ * 4);
    // 最多取9个就可以分胜负
    for(int i = 0; i < 9; ++ i)
    {
        //std::cout << "x: " << x << " y: " << start + (i * line_cr_) << std::endl;
        int new_x = start_x + (i * line_cr_);
        int new_y = start_y - (i * line_cr_);
        std::string map_key = gerer_key(new_x, new_y);
        std::map<std::string, ChesPieces>::iterator search_map;
        search_map = xy_mapper_.find(map_key);
        // 找到了，说明目标位标有棋子
        int search_color = 0;
        if(search_map != xy_mapper_.end())
        {
            ChesPieces search_cp = xy_mapper_[map_key];
            search_color = search_cp.color();
        }
        coll_two.insert(std::end(coll_two), search_color);
    }
    std::vector<int>::iterator serarch_n_iter;
    // 有五个相同的棋子，分出胜负
    serarch_n_iter = std::search_n(std::begin(coll_two), std::end(coll_two), 5, current_color_);
    if(serarch_n_iter != std::end(coll_two))
    {
        return true;
    }
    return false;
}
void SimpleWin::change_size(SimpleWin* win)
{
    const char *input = fl_input(u8"棋盘大小(多少线):", std::to_string(line_size_).c_str());
    if (input)
    {
        // string 转 int
        int new_line = atoi(input);
        if(!new_line){ fl_alert(u8"无效输入"); return;}
        if(new_line < 11){ fl_alert(u8"棋盘最小为11条线"); return;};
        if(new_line > 25){ fl_alert(u8"棋盘最大为25条线"); return;};
        line_size_ = new_line;
        win->redraw();
    }
}
